#ifndef MODULE_H_
#define MODULE_H_

#include <stdint.h>
#include <sys/time.h>
#include <sys/types.h>
#include "device.h"
#include "crypto.h"
//#include "keymgt.h"
#include "sec_api.h"
#include "autoconfig.h"
#include "prn_drv.h"
#include "lcd_attr.h"

typedef struct {
        /* File Operation */
        int (*open)(const char *pathname, int oflag, ... /* mode_t mode */);
        int (*close)(int fd);
        ssize_t (*read)(int fd, void * buffer, size_t len);
        ssize_t (*write)(int fd, const void * buffer, size_t len);
        int (*select)(int nfds, fd_set *readfds, fd_set *writefds,
                   fd_set *exceptfds, struct timeval *timeout);
        off_t (*lseek)(int fd, off_t offset, int whence);
		int (*truncate)(int fd,off_t length);
        int (*unlink)(const char * pathname);
		int (*ioctl)(int fd, int cmd, void *arg);
		
        /* Time & Date Operation */
        int (*gettimeofday)(struct timeval *tv, struct timezone *tz);
        int (*settimeofday)(const struct timeval *tv , const struct timezone *tz);
		/* timeout control */
        uint32_t (*timeout_start)(void);
        uint32_t (*timeout_test)(uint32_t *start, uint32_t *ms);

        /* LCD Utility */
        int (*lcd_set_attribute)(uint8_t atr, void * arg);
        void (*lcd_backlight)(uint32_t onff);
        void (*lcd_clrscr)(void);
        int (*lcd_disp_img)(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t * img);
        int (*lcd_disp_string)(uint32_t x, uint32_t y, char * string);
        int (*lcd_disp_hline)(uint32_t x, uint32_t y, uint32_t w);
        int (*lcd_disp_vline)(uint32_t x, uint32_t y, uint32_t h);

        /* Keypad Utility */
        int (*kb_get_key)(int ms);
        int (*kb_get_str)(char * input, int in_len, 
                            int min_len, int max_len, 
                            int timeout, char show, int mode);
        int (*kb_get_amount)(char * amount, int max_len, int timeout);
        /* POS Entry */
        int (*pos_entry)(pos_entry_t entry, pos_entry_un *data, int ms);

        int (*serial_init)(uint32_t id, serial_info_t * info);
        int (*serial_write)(uint32_t id, uint8_t * buffer, size_t len);
        int (*serial_read)(uint32_t id, uint8_t * buffer, size_t len, int timeout);
        int (*serial_clrbuf)(uint32_t id, int rx, int tx);
        
		int (*icc_status)( uint8_t *status, int *status_len );
        int (*icc_power_up)( int cardno, uint8_t *out, int *outlen );
        int (*icc_send_apdu)( int cardno, uint8_t* in, int inlen, uint8_t *out, int *outlen );
        int (*icc_power_down)( int cardno );
		
        /* Crypto */
        void (*sha1_starts)(void);
        void (*sha1_update)(uint8_t *input, int ilen);
        void (*sha1_finish)(uint8_t output[20]);
		int (*sha2_starts)(int is224);
        void (*sha2_update)(uint8_t* input, uint32_t length);
        void (*sha2_finish)(uint8_t digest[32]);
        int (*deskey)(uint8_t key[8], int decrypt);
        int (*des)(uint8_t block[8], uint8_t output[8]);
        int (*des3key2)(uint8_t key[16], int decrypt);
        int (*des3key3)(uint8_t key[24], int decrypt);
        int (*des3)(uint8_t block[8], uint8_t output[8]);
        int (*rsapublicfunc)(uint8_t *output,uint32_t *outputLen,
        uint8_t *input, uint32_t inputLen,R_RSA_PUBLIC_KEY *publicKey );

        uint8_t (*rng_get_byte)(void);
        int (*rng_get_string)(uint8_t * buf, uint32_t len);
        uint16_t (*crc16)(uint16_t crc, uint8_t *buffer, uint32_t len);
        uint16_t (*crc16_itu_t)(uint16_t crc, uint8_t *buffer, uint32_t len);
        uint32_t (*crc32)(uint32_t crc, uint8_t *buffer, uint32_t len);

        /* Code Utility */
        int (*asc2bcd)(char * ascstr, int len, uint8_t *bcdstr, int align);
        int (*bcd2asc)(uint8_t * bcd, int asclen, char * asc, int align);

        /* Key */
        int (*sec_key_injection)( void );
        int (*sec_crl_injection)( void );
        int (*sec_get_keygrp_no)( uint8_t *fid, uint8_t *gid );
        int (*sec_set_curr_keygrp)( uint8_t fid, uint8_t gid );
        int (*sec_pin_encrypt)( pin_block_type_t format, sec_pin_encrypt_t *info, 
							uint8_t * result);
        int (*sec_set_workkey)( uint8_t fid, uint8_t gid, 
                        uint8_t type, sec_set_workkey_t *key_info );
		int (*sec_mac_x919)(uint8_t* in, uint32_t len, uint8_t *out);
        int (*sec_track_encrypt)( uint8_t *track_bcd, int len );
        /* Module Library */
        void * (*sys_load_library)(char *name);
        int (*sys_run_app)(char *name);
        int (*sys_update_mod)(mod_update_t *update, uint8_t nr);
		
        /* Misc Operation */
		void (*reset)(void);
        void (*mdelay)(uint32_t ms);               /**< Delay Milliseconds */
        void (*buzzer_start)(void);
        void (*buzzer_stop)(void);
        void (*led_ctrl)(uint32_t nr, uint32_t on);
        uint32_t (*security_status)(void);
        int (*nv_write)(uint32_t offset, uint8_t * buf, int buflen);
        int (*nv_read)(uint32_t offset, uint8_t * buf, int buflen);
        int (*sys_get_param)(uint32_t type, void *buf, uint32_t len);
        int (*sys_set_param)(uint32_t type, void *buf, uint32_t len);

        int (*sec_mac_dc_ecb)(uint8_t* in, int len, uint8_t *out);
        int (*sec_unset_key)( uint8_t fid, uint8_t gid, uint8_t type );
        int (*sec_set_masterkey)( uint8_t gid, sec_set_masterkey_t *key_info );
        int (*sec_update_masterkey)( uint8_t gid, upt_masterkey_t *key_info );

        int (*sec_sm2_verify_signature)( sm2_sign_t *sign, sm2_para_t *para );
        int (*sec_sm3_calc)( uint8_t *in, int len, uint8_t *out );
        int (*sec_mac_x99)(uint8_t* in, uint32_t len, uint8_t *out);

        int (*sys_cpufreq_notify_transition)(unsigned long freq,  void *data);

		/* MODEM API */
		int (*modem_get_sq)(void);
		int (*modem_get_info)(modem_info_em type, char *info);
		int (*modem_get_station_info)(modem_station_info_t *info); 

		/*TCP API*/
        int (*tcp_open)(tcp_dev_em type); 
        int (*tcp_close)(int fd); 
        int (*tcp_connect)(int fd, const char *ip, int port, int timeout);	 
        int (*tcp_write)(int fd, const char* data, int data_len, int timeout);	 
        int (*tcp_read)(int fd, char* buf, int req_len, int timeout);	
		
		/* Printer API */
		int (*prn_start)(void);
        void (*prn_putch)(char ch, char **pca);
		int  (*prn_string)( const char *str, ... );
		int (*prn_set_font)(hz_font_em hz_font, zm_font_em zm_font);
		int (*prn_set_underline)(uint8_t pstatus);
		int (*prn_set_spacing)(int border, int column, int row);
		int (*prn_set_grey)(uint8_t grey);
		int (*prn_get_status)( prn_status_em *status);
		int (*prn_image)(int x_size, int y_size, int x_pos, const char *img);
		int (*prn_init)(void);
		int (*sec_mac_9606)(uint8_t* in, uint32_t len, uint8_t *out);
        int (*sys_sleep)(int sleep, void *flush_func, int flush_time);
		int (*lcd_get_type)(void);
		int (*lcd_push)(void);
		int (*lcd_pop)(void);
		int (*lcd_clrscr_line)(uint32_t start_y, uint32_t end_y);
		int (*lcd_goto_xy)(uint32_t x, uint32_t y);
		int (*lcd_get_xy)(uint32_t *px, uint32_t *py);
		int (*lcd_set_view_port)(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
		int (*lcd_get_view_port)(uint32_t *px, uint32_t *py, uint32_t *pw, uint32_t *ph);
		void (*lcd_putch)(char ch, char **pca);
		int (*lcd_set_font)(lcd_font_type_em emtype);
		int (*lcd_set_space)(uint32_t wspace, uint32_t hspace);
		int (*lcd_get_size)(uint32_t * pwidth, uint32_t * pheight);
		int (*lcd_set_contrast)(uint32_t contrast);
		int (*lcd_statusbar)(lcd_statusbar_em  new_flag, lcd_statusbar_em  *pold_flag);
        int (*sys_read_battery_status)(uint32_t *voltage, uint8_t *level, uint32_t *button_vol);
		/*DAC*/
		int (*voice_ctrl_volume)(uint32_t vol);
        int (*voice_file_play)(char * pszFile);
        int (*sys_pm_ctrl)(int onoff);

		/*crypt variant*/
		int (*sec_track_cryptv)( int type, sec_track_info_t *track_info );
		int (*sec_pin_cryptv)( int type, pin_block_type_t format, sec_pin_info_t *info );
		int (*sec_mac_cryptv)( int type, sec_mac_info_t *mac_info );
		int (*sec_data_cryptv)( int type, sec_data_info_t *data_info );
        
        int (*get_ascii_str)(uint32_t x, uint32_t y, char * buf, uint32_t minlen,
                        uint32_t maxlen, uint32_t secs, char show);
}sys_api_t;

typedef struct {
        uint32_t magic_num;
        uint32_t text_start;
        uint32_t text_end;
        uint32_t data_start;
        uint32_t data_end;
        uint32_t bss_start;
        uint32_t bss_end;
        int (*module_init)(sys_api_t *);
        int (*module_main)(void);
        void* (*module_export)(void);
}module_t;

#define _module_header_entry __attribute__ ((__used__,section (".mod.header")))
#define MODULE_MAGIC    0x72786D64

module_t * load_module(char *name);
void * sys_load_library(char *name);
int sys_run_app(char *name);
const char * get_sys_version(void);


#define PART_NAME_MAX 14
#define MODULE_SHA256_LEN 26
typedef struct {
        uint8_t head;
        uint8_t hash_flag;
        uint8_t public_key;
        uint8_t time[3];
        char name[PART_NAME_MAX]; /* The above 4-byte aligned */
        uint32_t length;
        uint8_t firmware_type;
        uint8_t resev[2];
        uint8_t sha256[32];
        uint8_t end;
}headinfo_t;

typedef struct {
	uint8_t magc[8];
	uint8_t type;
	uint8_t date[7];
	uint32_t length;
	uint8_t owner_svr[12];
	uint8_t sha256[32];
	uint8_t usr_svr[192];
} sysheadinfo_t;	// file head info


int decode_signature(uint8_t * sig, headinfo_t* app, module_t *pmod);
int verify_firmware(char * name);

#endif /* MODULE_H_ */
